package effective;

import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toList;
import static java.util.Comparator.comparing;
import static java.util.function.BinaryOperator.maxBy;

import java.util.Collections;
import java.util.stream.Stream;
import java.util.List;

class CollectionsDemo {
  enum Suit {
    HeiTao,
    HongTao,
    MeiHua,
    FangPian;
  }
  enum Rank {
    One,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    J,
    Q,
    K,
    A
  }
  static class Card {
    private Rank rank;
    private Suit suit;
    Card(Rank r, Suit s) {
      this.rank = r;
      this.suit = s;
    }

    Rank getRank() {
      return rank;
    }

    Suit getSuit() {
      return suit;
    }
    
    @Override 
    public String toString() {
      return String.format("%s{%s}", this.suit, this.rank);
    }
  }

  static class Deck {
    static List<Card> ZhengFuPai() {
      return Stream.of(Suit.values()).
              flatMap(s -> 
                 Stream.of(Rank.values())
                  .map(r -> new Card(r, s)) 
              ).collect(toList());
    }

    static List<Card> SuijiFaPai(int n) {
      List<Card> ret = ZhengFuPai();
      Collections.shuffle(ret);
      return ret.subList(0, Math.min(ret.size(), n));
    }
  }


  public static void main(String[] args) {
    List<Card> deck = Deck.SuijiFaPai(15);
    System.out.println(deck);
    System.out.println(deck.stream().collect(
      groupingBy(card -> card.suit, counting())));
    // System.out.println(deck.stream().collect(
    //               toMap(Card::getSuit, c->c)));
    
    // Comparator<Card> cmp = comparing(Card::getRank);
    // deck.sort(cmp);
    // System.out.println(deck);
    // System.out.println(deck.stream().collect(
    //               toMap(Card::getSuit, c->c, 
    //               (x, y) -> cmp.compare(x, y) > 0 ? x : y)));
    // 注意这里是BinaryOperator的maxBy，不是Collectors里的maxBy
    System.out.println(deck.stream().collect(
                  toMap(Card::getSuit, c->c, 
                  maxBy(comparing(Card::getRank)))));
  }
}